<?php

/**
 * PagerTest
 *
 * @author vbolshov
 */

use km\util\Uploader;
use km\util\Uploader_Entry;
use km\util\Uploader_InvalidKeyException;
use km\util\Uploader_MissingRequiredFilesException;

require_once dirname(__FILE__) . '/../../lib/km/util/Uploader.php';
require_once dirname(__FILE__) . '/../../lib/km/util/Uploader/Entry.php';
require_once dirname(__FILE__) . '/../../lib/km/util/Uploader/Exception.php';
require_once dirname(__FILE__) . '/../../lib/km/util/Uploader/InvalidKeyException.php';
require_once dirname(__FILE__) . '/../../lib/km/util/Uploader/MissingRequiredFilesException.php';

define('TEST_UPLOAD_NAME', 'test_upload.txt');
define('TEST_UPLOAD', dirname(__FILE__) . '/../files/' . TEST_UPLOAD_NAME);
define('TEST_UPLOAD_DIR', dirname(__FILE__) . '/../tmp');

class UploaderTest extends PHPUnit_Framework_TestCase {
	/**
	 * @var array
	 */
	private $single_upload_err_no_file = array(
		't1' => array(
			'name' => 'test',
			'type' => 'test',
			'tmp_name' => 'test',
			'error' => UPLOAD_ERR_NO_FILE,
		)
	);
	/**
	 * @var array
	 */
	private $multiple_uploads = array(
		't1' => array(
			'name' => array('t1_1', 't1_2'),
			'type' => array('test', 'test'),
			'tmp_name' => array('t1_1', 't1_2'),
			'error' => array(UPLOAD_ERR_OK, UPLOAD_ERR_NO_FILE),
		),
		't2' => array(
			'name' => array('t2_1', 't2_2'),
			'type' => array('test', 'test'),
			'tmp_name' => array('t2_1', 't2_2'),
			'error' => array(UPLOAD_ERR_OK, UPLOAD_ERR_NO_FILE),
		)
	);
	private $existing_file = array(
		't1' => array(
			'name' => TEST_UPLOAD_NAME,
			'type' => 'text/plain',
			'tmp_name' => TEST_UPLOAD,
			'error' => UPLOAD_ERR_OK,
		)
	);
	
	function testExceptionThrowOnNonExistingKey()
	{
		try {
			new Uploader('non-existing');
			$this->fail('Uploader_InvalidKeyException should have been thrown');
		} catch (Uploader_InvalidKeyException $e) {
			$this->assertTrue(true);
		}
	}
	function testSingleUploadThrowsExceptionWhenMissingRequiredFiles()
	{
		$_FILES = $this->single_upload_err_no_file;
		try {
			new Uploader('t1', Uploader::ALL);
			$this->fail('Uploader_MissingRequiredFilesException should have been thrown');
		} catch (Uploader_MissingRequiredFilesException $e) {
			$this->assertTrue(true);
		}
	}
	function testMultipleUploadThrowsExceptionWhenMissingRequiredFiles()
	{
		$_FILES = $this->multiple_uploads;
		try {
			new Uploader(array('t1', 't2'), Uploader::ALL);
			$this->fail('Uploader_MissingRequiredFilesException should have been thrown');
		} catch (Uploader_MissingRequiredFilesException $e) {
			$this->assertTrue(true);
		}
	}
	function testMultipleUploadNotThrowsExceptionWhenRequiredFilesAreUploaded()
	{
		$_FILES = $this->multiple_uploads;
		try {
			new Uploader(array('t1', 't2'), 2);
			$this->assertTrue(true);
		} catch (Uploader_MissingRequiredFilesException $e) {
			$this->fail('Uploader_MissingRequiredFilesException should NOT have been thrown');
		}
	}
	function testMoveUploadedFile()
	{
		$uploader = $this->validUploader($uploaded);
		
		$this->assertEquals(1, $uploader->move(TEST_UPLOAD_DIR));
		$this->assertTrue(is_file($uploaded));
		
		@unlink($uploaded);
	}
	function testListenersCancelMove()
	{
		$uploader = $this->validUploader($uploaded);
		
		$uploader->onBeforeMove(function(Uploader_Entry $entry){
			return false;
		});
		
		$this->assertEquals(0, $uploader->move(TEST_UPLOAD_DIR));
		$this->assertFalse(is_file($uploaded));
	}
	function testExtensionFilter()
	{
		$uploader = $this->validUploader($uploaded);
		
		$uploader->acceptExtension('xxx');
		
		$this->assertEquals(0, $uploader->move(TEST_UPLOAD_DIR));
		$this->assertFalse(is_file($uploaded));
	}
	function testTypeFilter()
	{
		$uploader = $this->validUploader($uploaded);
		
		$uploader->acceptType('xxx');
		
		$this->assertEquals(0, $uploader->move(TEST_UPLOAD_DIR));
		$this->assertFalse(is_file($uploaded));
	}
	function testPatternFilter()
	{
		$uploader = $this->validUploader($uploaded);
		
		$uploader->acceptPattern("/xxx\.xxx/");
		
		$this->assertEquals(0, $uploader->move(TEST_UPLOAD_DIR));
		$this->assertFalse(is_file($uploaded));
	}
	function testAfterMoveFilter()
	{
		$uploader = $this->validUploader($uploaded);
		
		$uploader->onAfterMove(function(Uploader_Entry $entry){
			return false;
		});
		
		$this->assertEquals(1, $uploader->move(TEST_UPLOAD_DIR));
		$this->assertTrue(is_file($uploaded));
		
		$uploader->deleteFilesThatFailedPostprocessing();
		$this->assertFalse(is_file($uploaded));
	}
	function testRollback()
	{
		$uploader = $this->validUploader($uploaded);
		
		$this->assertEquals(1, $uploader->move(TEST_UPLOAD_DIR));
		$this->assertTrue(is_file($uploaded));
		
		$uploader->rollback();
		$this->assertFalse(is_file($uploaded));
	}
	
	private function validUploader(& $filename)
	{
		$filename = TEST_UPLOAD_DIR . '/' . TEST_UPLOAD_NAME;
		@unlink($filename);
		
		$_FILES = $this->existing_file;
		return new Uploader('t1', Uploader::ALL);
	}
}